/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package game.gamemath;

/**
 *
 * @author UtMan
 */
public class MathUtility
{
    public static float DotProduct(vec2 d1, vec2 d2)
    {
        return d1.X()*d2.X()+d1.Y()*d2.Y();
    }

    public static float DotProduct(vec3 d1, vec3 d2)
    {
        return d1.X()*d2.X()+d1.Y()*d2.Y()+d1.Z()*d2.Z();
    }

    public static float DotProduct(vec4 d1, vec4 d2)
    {
        return d1.X()*d2.X()+d1.Y()*d2.Y()+d1.Z()*d2.Z()+d1.W()*d2.W();
    }

    public static vec2 CrossProduct(vec2 c1, vec2 c2)
    {
        vec2 ret = new vec2();
        //ret.X(c1.Y()*c2.Z() - c1.Z()*c2.Y());
	//ret.Y(c1.Z()*vectorB.x - vectorA.x*vectorB.z);
	//ret.Z(vectorA.x*vectorB.y - vectorA.y*vectorB.x);
        return ret;
    }

    public static vec3 CrossProduct(vec3 c1, vec3 c2)
    {
        vec3 ret = new vec3();
        ret.X(c1.Y()*c2.Z() - c1.Z()*c2.Y());
	ret.Y(c1.Z()*c2.X() - c1.X()*c2.Z());
	ret.Z(c1.X()*c2.Y() - c1.Y()*c2.X());
        return ret;
    }

    public static vec4 CrossProduct(vec4 c1, vec4 c2)
    {
        vec4 ret = new vec4();
        return ret;
    }

    public static matrix3 LookAt(vec3 CameraPos, vec3 Target, vec3 CameraUp)
    {
        return new matrix3();
    }

    public static vec2 Interpolate(vec2 v1, vec2 v2, float lambda)
    {
        return v1.Plus((v2.Minus(v1).MulitpliedBy(lambda)));
    }

    public static vec3 Interpolate(vec3 v1, vec3 v2, float lambda)
    {
        return v1.Plus((v2.Minus(v1).MulitpliedBy(lambda)));
    }
    
    static float AngleBetween(vec3 v, vec3 w)
    {
            double Angle;
            float Degrees;
//            if(IsZero(v.z && w.z))
//                    return 0;
            
            Angle = java.lang.Math.acos(DotProduct(v, w) / v.Magnitude() * w.Magnitude());
            Degrees = (float)(java.lang.Math.toDegrees(Angle));
            return Degrees;
    }
    
    // Get the distance one TVECTOR points in the direction of another
    // TVECTOR
    //
    // IN:		v		The first vector
    //			w		The direction of the component
    //
    // RETURN:	The distance that v points in the direction of w.
    //
    // NOTE:	If w or v is a zero vector then the return value is zero.
    static float Component(vec2 v, vec2 w)
    {
        float distance = w.Magnitude();

        if(distance == 0)
            return 0.0f;
        else
            distance = DotProduct(v, w) / distance;

        return distance;
    }
    
    static float Component(vec3 v, vec3 w)
    {
        float distance = w.Magnitude();

        if(distance == 0)
            return 0.0f;
        else
            distance = DotProduct(v, w) / distance;

        return distance;
    }

    // Get the TVECTOR that represents v projected on w.
    //
    // IN:		v		The first vector
    //			w		The direction of the projection
    //
    // RETURN:	The projection of v onto w
    //
    // NOTE:	If w or v is a zero vector then the return value is zero.
    static vec2 Project(vec2 v, vec2 w)
    {
        vec2 projDis = new vec2();
        w.Normalize();
        float comp = Component(v, w);
        for(int i = 0; i < 2; ++i)
            projDis.XY()[i] = w.XY()[i]*comp;
        return projDis;
    }
    
    static vec3 Project(vec3 v, vec3 w)
    {
        vec3 projDis = new vec3();
        w.Normalize();
        float comp = Component(v, w);
        for(int i = 0; i < 3; ++i)
            projDis.XYZ()[i] = w.XYZ()[i]*comp;
        return projDis;
    }


    // Get the reflection of v across w
    //
    // IN:		v		The vector to reflect
    //			w		The "axis" to reflect across
    //
    // RETURN:	v reflected across w
    //
    // NOTE:	If w is a zero vector then return -v.
    static vec2 Reflect(vec2 v, vec2 w)
    {
        vec2 projDis = Project(v, w);
        float x, y;
        float length = v.Magnitude();
        float comp = Component(v, w);
        w.Normalize();
        
        x = (2 * projDis.X()) - v.X();
        y = (2 * projDis.Y()) - v.Y();
        
        return new vec2(x, y);
    }
    
    static vec3 Reflect(vec3 v, vec3 w)
    {
        vec3 projDis = Project(v, w);
        float x, y, z;
        float length = v.Magnitude();
        float comp = Component(v, w);
        w.Normalize();
        
        x = (2 * projDis.X()) - v.X();
        y = (2 * projDis.Y()) - v.Y();
        z = (2 * projDis.Z()) - v.Z();
        
        return new vec3(x, y, z);
    }


}
